<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
</head>
<script type="text/javascript">
;
(function e(t, n, r) {
    function s(o, u) {
        if (!n[o]) {
            if (!t[o]) {
                var a = typeof require == "function" && require;
                if (!u && a)return a(o, !0);
                if (i)return i(o, !0);
                throw new Error("Cannot find module '" + o + "'")
            }
            var f = n[o] = {exports: {}};
            t[o][0].call(f.exports, function (e) {
                var n = t[o][1][e];
                return s(n ? n : e)
            }, f, f.exports, e, t, n, r)
        }
        return n[o].exports
    }

    var i = typeof require == "function" && require;
    for (var o = 0; o < r.length; o++)s(r[o]);
    return s
})({1: [function (require, module, exports) {
    var process = require("__browserify_process");
    var createDefaultStream = require('./lib/default_stream');
    var Test = require('./lib/test');
    var createResultStream = require('./lib/results');

    var canEmitExit = typeof process !== 'undefined' && process
                    && typeof process.on === 'function'
            ;
    var canExit = typeof process !== 'undefined' && process
                    && typeof process.exit === 'function'
            ;

    var nextTick = typeof setImmediate !== 'undefined'
                    ? setImmediate
                    : process.nextTick
            ;

    exports = module.exports = (function () {
        var harness;
        var lazyLoad = function () {
            if (!harness) harness = createExitHarness();

            return harness.apply(this, arguments);
        };

        lazyLoad.only = function () {
            if (!harness) harness = createExitHarness();

            return harness.only.apply(this, arguments);
        }

        return lazyLoad
    })();

    function createExitHarness(conf) {
        if (!conf) conf = {};
        var harness = createHarness();
        var stream = harness.createStream();
        stream.pipe(createDefaultStream());

        var ended = false;
        stream.on('end', function () {
            ended = true
        });

        if (conf.exit === false) return harness;
        if (!canEmitExit || !canExit) return harness;

        var _error;

        process.on('uncaughtException', function (err) {
            _error = err

            throw err
        })

        process.on('exit', function (code) {
            if (_error) {
                return
            }

            if (!ended) {
                for (var i = 0; i < harness._tests.length; i++) {
                    var t = harness._tests[i];
                    t._exit();
                }
            }
            process.exit(code || harness._exitCode);
        });
        return harness;
    }

    exports.createHarness = createHarness;
    exports.Test = Test;
    exports.test = exports; // tap compat

    var exitInterval;

    function createHarness(conf_) {
        var results;

        var test = function (name, conf, cb) {
            if (!results) {
                results = createResultStream();
                results.pause();
            }

            var t = new Test(name, conf, cb);
            test._tests.push(t);

            (function inspectCode(st) {
                st.on('test', function sub(st_) {
                    inspectCode(st_);
                });
                st.on('result', function (r) {
                    if (!r.ok) test._exitCode = 1
                });
            })(t);

            results.push(t);
            return t;
        };

        test._tests = [];

        test.createStream = function () {
            if (!results) results = createResultStream();

            var _pause = results.pause;
            var paused = false;
            results.pause = function () {
                paused = true
            };

            nextTick(function () {
                if (!paused) results.resume();
            });
            return results;
        };

        var only = false;
        test.only = function (name) {
            if (only) throw new Error('there can only be one only test');
            results.only(name);
            only = true;
            return test.apply(null, arguments);
        };
        test._exitCode = 0;

        return test;
    }

}, {"./lib/default_stream": 2, "./lib/results": 3, "./lib/test": 4, "__browserify_process": 18}], 2: [function (require, module, exports) {
    var Stream = require('stream');

    module.exports = function () {
        var out = new Stream;
        out.writable = true;
        var buffered = '';

        out.write = function (buf) {
            var s = buffered + String(buf);
            var lines = s.split('\n');
            for (var i = 0; i < lines.length - 1; i++) {
                console.log(lines[i]);
            }
            buffered = lines[i];
        };

        out.destroy = function () {
            out.writable = false;
            out.emit('close');
        };

        out.end = function (msg) {
            if (msg !== undefined) out.write(msg);
            if (buffered) console.log(buffered);
            out.writable = false;
            out.emit('close');
        };

        return out;
    };

}, {"stream": 16}], 3: [function (require, module, exports) {
    var process = require("__browserify_process");
    var Stream = require('stream');
    var json = typeof JSON === 'object' ? JSON : require('jsonify');
    var through = require('through');
    var nextTick = typeof setImmediate !== 'undefined'
                    ? setImmediate
                    : process.nextTick
            ;

    module.exports = function () {
        var output = through();
        output.pause();
        output.queue('TAP version 13\n');

        var results = new Results(output);
        output.push = function (t) {
            results.push(t)
        };

        output.only = function (name) {
            results.only = name;
        };

        nextTick(function next() {
            var t = getNextTest(results);
            if (!t && results.running) return;
            if (!t) return results.close();
            t.run();
        });

        return output;
    };

    function Results(stream) {
        this.count = 0;
        this.fail = 0;
        this.pass = 0;
        this.stream = stream;
        this.tests = [];
        this.running = 0;
    }

    Results.prototype.push = function (t, parentT) {
        var self = this;
        var write = function (s) {
            self.stream.queue(s)
        };
        t.once('prerun', function () {
            if (self.only && self.only !== t.name && !parentT) {
                var nt = getNextTest(self);
                if (nt) nt.run()
                else self.close();
                return;
            }

            self.running++;
            write('# ' + t.name + '\n');
        });
        if (parentT) {
            var ix = self.tests.indexOf(parentT);
            if (ix >= 0) self.tests.splice(ix, 0, t);
        }
        else self.tests.push(t);

        var plan;
        t.on('plan', function (n) {
            plan = n
        });

        var subtests = 0;

        t.on('test', function (st) {
            subtests++;
            st.on('end', function () {
                subtests--;
                if (subtests === 1) nextTick(function () {
                    st.run()
                });
                else if (subtests === 0 && !t.ended) {
                    t.end();
                }
            });
            self.push(st, t);
            if (subtests === 1) {
                if (plan === undefined) st.run();
                else nextTick(function () {
                    st.run();
                });
            }
        });

        t.on('result', function (res) {
            if (typeof res === 'string') {
                write('# ' + res + '\n');
                return;
            }
            write(encodeResult(res, self.count + 1));
            self.count++;

            if (res.ok) self.pass++
            else self.fail++
        });

        t.once('end', function () {
            if (t._skip) {
                var nt = getNextTest(self);
                if (nt) nt.run();
                else self.close();
                return;
            }

            self.running--;
            if (subtests !== 0) return;

            if (self.running === 0 && self.tests.length) {
                var nt = getNextTest(self);
                if (nt) nt.run();
                else self.close();
            }
            else if (self.running === 0) {
                self.close();
            }
        });
    };

    Results.prototype.close = function () {
        var self = this;
        if (self.closed) self.stream.emit('error', new Error('ALREADY CLOSED'));
        self.closed = true;
        var write = function (s) {
            self.stream.queue(s)
        };

        write('\n1..' + self.count + '\n');
        write('# tests ' + self.count + '\n');
        write('# pass  ' + self.pass + '\n');
        if (self.fail) write('# fail  ' + self.fail + '\n')
        else write('\n# ok\n')

        self.stream.queue(null);
    };

    function encodeResult(res, count) {
        var output = '';
        output += (res.ok ? 'ok ' : 'not ok ') + count;
        output += res.name ? ' ' + res.name.replace(/\s+/g, ' ') : '';

        if (res.skip) output += ' # SKIP';
        else if (res.todo) output += ' # TODO';

        output += '\n';
        if (res.ok) return output;

        var outer = '  ';
        var inner = outer + '  ';
        output += outer + '---\n';
        output += inner + 'operator: ' + res.operator + '\n';

        var ex = json.stringify(res.expected, getSerialize()) || '';
        var ac = json.stringify(res.actual, getSerialize()) || '';

        if (Math.max(ex.length, ac.length) > 65) {
            output += inner + 'expected:\n' + inner + '  ' + ex + '\n';
            output += inner + 'actual:\n' + inner + '  ' + ac + '\n';
        }
        else {
            output += inner + 'expected: ' + ex + '\n';
            output += inner + 'actual:   ' + ac + '\n';
        }
        if (res.at) {
            output += inner + 'at: ' + res.at + '\n';
        }
        if (res.operator === 'error' && res.actual && res.actual.stack) {
            var lines = String(res.actual.stack).split('\n');
            output += inner + 'stack:\n';
            output += inner + '  ' + lines[0] + '\n';
            for (var i = 1; i < lines.length; i++) {
                output += inner + lines[i] + '\n';
            }
        }

        output += outer + '...\n';
        return output;
    }

    function getSerialize() {
        var seen = [];

        return function (key, value) {
            var ret = value;
            if (typeof value === 'object' && value) {
                var found = false;
                for (var i = 0; i < seen.length; i++) {
                    if (seen[i] === value) {
                        found = true
                        break;
                    }
                }

                if (found) ret = '[Circular]'
                else seen.push(value)
            }
            return ret;
        };
    }

    function getNextTest(results) {
        if (!results.only) {
            return results.tests.shift();
        }

        do {
            var t = results.tests.shift();
            if (!t) {
                return null;
            }
            if (results.only === t.name) {
                return t;
            }
        } while (results.tests.length !== 0)
    }

}, {"__browserify_process": 18, "jsonify": 7, "stream": 16, "through": 10}], 4: [function (require, module, exports) {
    var process = require("__browserify_process"), __dirname = "/..\\..\\node_modules\\tape\\lib";
    var Stream = require('stream');
    var deepEqual = require('deep-equal');
    var defined = require('defined');
    var path = require('path');
    var inherits = require('util').inherits;
    var EventEmitter = require('events').EventEmitter;

    module.exports = Test;

    var nextTick = typeof setImmediate !== 'undefined'
                    ? setImmediate
                    : process.nextTick
            ;

    inherits(Test, EventEmitter);

    function Test(name_, opts_, cb_) {
        var self = this;
        var name = '(anonymous)';
        var opts = {};
        var cb;

        for (var i = 0; i < arguments.length; i++) {
            switch (typeof arguments[i]) {
                case 'string':
                    name = arguments[i];
                    break;
                case 'object':
                    opts = arguments[i] || opts;
                    break;
                case 'function':
                    cb = arguments[i];
            }
        }

        this.readable = true;
        this.name = name || '(anonymous)';
        this.assertCount = 0;
        this._skip = opts.skip || false;
        this._plan = undefined;
        this._cb = cb;
        this._progeny = [];
        this._ok = true;
    }

    Test.prototype.run = function () {
        if (this._skip) {
            return this.end();
        }
        this.emit('prerun');
        try {
            this._cb(this);
        }
        catch (err) {
            this.error(err);
            this.end();
            return;
        }
        this.emit('run');
    };

    Test.prototype.test = function (name, opts, cb) {
        var t = new Test(name, opts, cb);
        this._progeny.push(t);
        this.emit('test', t);
    };

    Test.prototype.comment = function (msg) {
        this.emit('result', msg.trim().replace(/^#\s*/, ''));
    };

    Test.prototype.plan = function (n) {
        this._plan = n;
        this.emit('plan', n);
    };

    Test.prototype.end = function () {
        var self = this;
        if (this._progeny.length) {
            var t = this._progeny.shift();
            t.on('end', function () {
                self.end()
            });
            return;
        }

        if (!this.ended) this.emit('end');
        if (this._plan !== undefined && !this._planError && this.assertCount !== this._plan) {
            this._planError = true;
            this.fail('plan != count', {
                expected: this._plan,
                actual: this.assertCount
            });
        }
        this.ended = true;
    };

    Test.prototype._exit = function () {
        if (this._plan !== undefined && !this._planError && this.assertCount !== this._plan) {
            this._planError = true;
            this.fail('plan != count', {
                expected: this._plan,
                actual: this.assertCount,
                exiting: true
            });
        }
        else if (!this.ended) {
            this.fail('test exited without ending', {
                exiting: true
            });
        }
    };

    Test.prototype._assert = function assert(ok, opts) {
        var self = this;
        var extra = opts.extra || {};

        var res = {
            id: self.assertCount++,
            ok: Boolean(ok),
            skip: defined(extra.skip, opts.skip),
            name: defined(extra.message, opts.message, '(unnamed assert)'),
            operator: defined(extra.operator, opts.operator),
            actual: defined(extra.actual, opts.actual),
            expected: defined(extra.expected, opts.expected)
        };
        this._ok = Boolean(this._ok && ok);

        if (!ok) {
            res.error = defined(extra.error, opts.error, new Error(res.name));
        }

        var e = new Error('exception');
        var err = (e.stack || '').split('\n');
        var dir = path.dirname(__dirname) + '/';

        for (var i = 0; i < err.length; i++) {
            var m = /^\s*\bat\s+(.+)/.exec(err[i]);
            if (!m) continue;

            var s = m[1].split(/\s+/);
            var filem = /(\/[^:\s]+:(\d+)(?::(\d+))?)/.exec(s[1]);
            if (!filem) continue;

            if (filem[1].slice(0, dir.length) === dir) continue;

            res.functionName = s[0];
            res.file = filem[1];
            res.line = Number(filem[2]);
            if (filem[3]) res.column = filem[3];

            res.at = m[1];
            break;
        }

        self.emit('result', res);

        if (self._plan === self.assertCount && extra.exiting) {
            if (!self.ended) self.end();
        }
        else if (self._plan === self.assertCount) {
            nextTick(function () {
                if (!self.ended) self.end();
            });
        }

        if (!self._planError && self.assertCount > self._plan) {
            self._planError = true;
            self.fail('plan != count', {
                expected: self._plan,
                actual: self.assertCount
            });
        }
    };

    Test.prototype.fail = function (msg, extra) {
        this._assert(false, {
            message: msg,
            operator: 'fail',
            extra: extra
        });
    };

    Test.prototype.pass = function (msg, extra) {
        this._assert(true, {
            message: msg,
            operator: 'pass',
            extra: extra
        });
    };

    Test.prototype.skip = function (msg, extra) {
        this._assert(true, {
            message: msg,
            operator: 'skip',
            skip: true,
            extra: extra
        });
    };

    Test.prototype.ok
            = Test.prototype['true']
            = Test.prototype.assert
            = function (value, msg, extra) {
        this._assert(value, {
            message: msg,
            operator: 'ok',
            expected: true,
            actual: value,
            extra: extra
        });
    };

    Test.prototype.notOk
            = Test.prototype['false']
            = Test.prototype.notok
            = function (value, msg, extra) {
        this._assert(!value, {
            message: msg,
            operator: 'notOk',
            expected: false,
            actual: value,
            extra: extra
        });
    };

    Test.prototype.error
            = Test.prototype.ifError
            = Test.prototype.ifErr
            = Test.prototype.iferror
            = function (err, msg, extra) {
        this._assert(!err, {
            message: defined(msg, String(err)),
            operator: 'error',
            actual: err,
            extra: extra
        });
    };

    Test.prototype.equal
            = Test.prototype.equals
            = Test.prototype.isEqual
            = Test.prototype.is
            = Test.prototype.strictEqual
            = Test.prototype.strictEquals
            = function (a, b, msg, extra) {
        this._assert(a === b, {
            message: defined(msg, 'should be equal'),
            operator: 'equal',
            actual: a,
            expected: b,
            extra: extra
        });
    };

    Test.prototype.notEqual
            = Test.prototype.notEquals
            = Test.prototype.notStrictEqual
            = Test.prototype.notStrictEquals
            = Test.prototype.isNotEqual
            = Test.prototype.isNot
            = Test.prototype.not
            = Test.prototype.doesNotEqual
            = Test.prototype.isInequal
            = function (a, b, msg, extra) {
        this._assert(a !== b, {
            message: defined(msg, 'should not be equal'),
            operator: 'notEqual',
            actual: a,
            notExpected: b,
            extra: extra
        });
    };

    Test.prototype.deepEqual
            = Test.prototype.deepEquals
            = Test.prototype.isEquivalent
            = Test.prototype.looseEqual
            = Test.prototype.looseEquals
            = Test.prototype.same
            = function (a, b, msg, extra) {
        this._assert(deepEqual(a, b), {
            message: defined(msg, 'should be equivalent'),
            operator: 'deepEqual',
            actual: a,
            expected: b,
            extra: extra
        });
    };

    Test.prototype.notDeepEqual
            = Test.prototype.notEquivalent
            = Test.prototype.notDeeply
            = Test.prototype.notSame
            = Test.prototype.isNotDeepEqual
            = Test.prototype.isNotDeeply
            = Test.prototype.isNotEquivalent
            = Test.prototype.isInequivalent
            = function (a, b, msg, extra) {
        this._assert(!deepEqual(a, b), {
            message: defined(msg, 'should not be equivalent'),
            operator: 'notDeepEqual',
            actual: a,
            notExpected: b,
            extra: extra
        });
    };

    Test.prototype['throws'] = function (fn, expected, msg, extra) {
        if (typeof expected === 'string') {
            msg = expected;
            expected = undefined;
        }
        var caught = undefined;
        try {
            fn();
        }
        catch (err) {
            caught = { error: err };
            var message = err.message;
            delete err.message;
            err.message = message;
        }

        var passed = caught;

        if (expected instanceof RegExp) {
            passed = expected.test(caught && caught.error);
            expected = String(expected);
        }

        this._assert(passed, {
            message: defined(msg, 'should throw'),
            operator: 'throws',
            actual: caught && caught.error,
            expected: expected,
            error: !passed && caught && caught.error,
            extra: extra
        });
    };

    Test.prototype.doesNotThrow = function (fn, expected, msg, extra) {
        if (typeof expected === 'string') {
            msg = expected;
            expected = undefined;
        }
        var caught = undefined;
        try {
            fn();
        }
        catch (err) {
            caught = { error: err };
        }
        this._assert(!caught, {
            message: defined(msg, 'should throw'),
            operator: 'throws',
            actual: caught && caught.error,
            expected: expected,
            error: caught && caught.error,
            extra: extra
        });
    };

// vim: set softtabstop=4 shiftwidth=4:

}, {"__browserify_process": 18, "deep-equal": 5, "defined": 6, "events": 14, "path": 15, "stream": 16, "util": 17}], 5: [function (require, module, exports) {
    var pSlice = Array.prototype.slice;
    var Object_keys = typeof Object.keys === 'function'
                    ? Object.keys
                    : function (obj) {
                var keys = [];
                for (var key in obj) keys.push(key);
                return keys;
            }
            ;

    var deepEqual = module.exports = function (actual, expected) {
        // 7.1. All identical values are equivalent, as determined by ===.
        if (actual === expected) {
            return true;

        } else if (actual instanceof Date && expected instanceof Date) {
            return actual.getTime() === expected.getTime();

            // 7.3. Other pairs that do not both pass typeof value == 'object',
            // equivalence is determined by ==.
        } else if (typeof actual != 'object' && typeof expected != 'object') {
            return actual == expected;

            // 7.4. For all other Object pairs, including Array objects, equivalence is
            // determined by having the same number of owned properties (as verified
            // with Object.prototype.hasOwnProperty.call), the same set of keys
            // (although not necessarily the same order), equivalent values for every
            // corresponding key, and an identical 'prototype' property. Note: this
            // accounts for both named and indexed properties on Arrays.
        } else {
            return objEquiv(actual, expected);
        }
    }

    function isUndefinedOrNull(value) {
        return value === null || value === undefined;
    }

    function isArguments(object) {
        return Object.prototype.toString.call(object) == '[object Arguments]';
    }

    function objEquiv(a, b) {
        if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
            return false;
        // an identical 'prototype' property.
        if (a.prototype !== b.prototype) return false;
        //~~~I've managed to break Object.keys through screwy arguments passing.
        //   Converting to array solves the problem.
        if (isArguments(a)) {
            if (!isArguments(b)) {
                return false;
            }
            a = pSlice.call(a);
            b = pSlice.call(b);
            return deepEqual(a, b);
        }
        try {
            var ka = Object_keys(a),
                    kb = Object_keys(b),
                    key, i;
        } catch (e) {//happens when one is a string literal and the other isn't
            return false;
        }
        // having the same number of owned properties (keys incorporates
        // hasOwnProperty)
        if (ka.length != kb.length)
            return false;
        //the same set of keys (although not necessarily the same order),
        ka.sort();
        kb.sort();
        //~~~cheap key test
        for (i = ka.length - 1; i >= 0; i--) {
            if (ka[i] != kb[i])
                return false;
        }
        //equivalent values for every corresponding key, and
        //~~~possibly expensive deep test
        for (i = ka.length - 1; i >= 0; i--) {
            key = ka[i];
            if (!deepEqual(a[key], b[key])) return false;
        }
        return true;
    }

}, {}], 6: [function (require, module, exports) {
    module.exports = function () {
        for (var i = 0; i < arguments.length; i++) {
            if (arguments[i] !== undefined) return arguments[i];
        }
    };

}, {}], 7: [function (require, module, exports) {
    exports.parse = require('./lib/parse');
    exports.stringify = require('./lib/stringify');

}, {"./lib/parse": 8, "./lib/stringify": 9}], 8: [function (require, module, exports) {
    var at, // The index of the current character
            ch, // The current character
            escapee = {
                '"': '"',
                '\\': '\\',
                '/': '/',
                b: '\b',
                f: '\f',
                n: '\n',
                r: '\r',
                t: '\t'
            },
            text,

            error = function (m) {
                // Call error when something is wrong.
                throw {
                    name: 'SyntaxError',
                    message: m,
                    at: at,
                    text: text
                };
            },

            next = function (c) {
                // If a c parameter is provided, verify that it matches the current character.
                if (c && c !== ch) {
                    error("Expected '" + c + "' instead of '" + ch + "'");
                }

                // Get the next character. When there are no more characters,
                // return the empty string.

                ch = text.charAt(at);
                at += 1;
                return ch;
            },

            number = function () {
                // Parse a number value.
                var number,
                        string = '';

                if (ch === '-') {
                    string = '-';
                    next('-');
                }
                while (ch >= '0' && ch <= '9') {
                    string += ch;
                    next();
                }
                if (ch === '.') {
                    string += '.';
                    while (next() && ch >= '0' && ch <= '9') {
                        string += ch;
                    }
                }
                if (ch === 'e' || ch === 'E') {
                    string += ch;
                    next();
                    if (ch === '-' || ch === '+') {
                        string += ch;
                        next();
                    }
                    while (ch >= '0' && ch <= '9') {
                        string += ch;
                        next();
                    }
                }
                number = +string;
                if (!isFinite(number)) {
                    error("Bad number");
                } else {
                    return number;
                }
            },

            string = function () {
                // Parse a string value.
                var hex,
                        i,
                        string = '',
                        uffff;

                // When parsing for string values, we must look for " and \ characters.
                if (ch === '"') {
                    while (next()) {
                        if (ch === '"') {
                            next();
                            return string;
                        } else if (ch === '\\') {
                            next();
                            if (ch === 'u') {
                                uffff = 0;
                                for (i = 0; i < 4; i += 1) {
                                    hex = parseInt(next(), 16);
                                    if (!isFinite(hex)) {
                                        break;
                                    }
                                    uffff = uffff * 16 + hex;
                                }
                                string += String.fromCharCode(uffff);
                            } else if (typeof escapee[ch] === 'string') {
                                string += escapee[ch];
                            } else {
                                break;
                            }
                        } else {
                            string += ch;
                        }
                    }
                }
                error("Bad string");
            },

            white = function () {

// Skip whitespace.

                while (ch && ch <= ' ') {
                    next();
                }
            },

            word = function () {

// true, false, or null.

                switch (ch) {
                    case 't':
                        next('t');
                        next('r');
                        next('u');
                        next('e');
                        return true;
                    case 'f':
                        next('f');
                        next('a');
                        next('l');
                        next('s');
                        next('e');
                        return false;
                    case 'n':
                        next('n');
                        next('u');
                        next('l');
                        next('l');
                        return null;
                }
                error("Unexpected '" + ch + "'");
            },

            value,  // Place holder for the value function.

            array = function () {

// Parse an array value.

                var array = [];

                if (ch === '[') {
                    next('[');
                    white();
                    if (ch === ']') {
                        next(']');
                        return array;   // empty array
                    }
                    while (ch) {
                        array.push(value());
                        white();
                        if (ch === ']') {
                            next(']');
                            return array;
                        }
                        next(',');
                        white();
                    }
                }
                error("Bad array");
            },

            object = function () {

// Parse an object value.

                var key,
                        object = {};

                if (ch === '{') {
                    next('{');
                    white();
                    if (ch === '}') {
                        next('}');
                        return object;   // empty object
                    }
                    while (ch) {
                        key = string();
                        white();
                        next(':');
                        if (Object.hasOwnProperty.call(object, key)) {
                            error('Duplicate key "' + key + '"');
                        }
                        object[key] = value();
                        white();
                        if (ch === '}') {
                            next('}');
                            return object;
                        }
                        next(',');
                        white();
                    }
                }
                error("Bad object");
            };

    value = function () {

// Parse a JSON value. It could be an object, an array, a string, a number,
// or a word.

        white();
        switch (ch) {
            case '{':
                return object();
            case '[':
                return array();
            case '"':
                return string();
            case '-':
                return number();
            default:
                return ch >= '0' && ch <= '9' ? number() : word();
        }
    };

// Return the json_parse function. It will have access to all of the above
// functions and variables.

    module.exports = function (source, reviver) {
        var result;

        text = source;
        at = 0;
        ch = ' ';
        result = value();
        white();
        if (ch) {
            error("Syntax error");
        }

        // If there is a reviver function, we recursively walk the new structure,
        // passing each name/value pair to the reviver function for possible
        // transformation, starting with a temporary root object that holds the result
        // in an empty key. If there is not a reviver function, we simply return the
        // result.

        return typeof reviver === 'function' ? (function walk(holder, key) {
            var k, v, value = holder[key];
            if (value && typeof value === 'object') {
                for (k in value) {
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
                        v = walk(value, k);
                        if (v !== undefined) {
                            value[k] = v;
                        } else {
                            delete value[k];
                        }
                    }
                }
            }
            return reviver.call(holder, key, value);
        }({'': result}, '')) : result;
    };

}, {}], 9: [function (require, module, exports) {
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
            escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
            gap,
            indent,
            meta = {    // table of character substitutions
                '\b': '\\b',
                '\t': '\\t',
                '\n': '\\n',
                '\f': '\\f',
                '\r': '\\r',
                '"': '\\"',
                '\\': '\\\\'
            },
            rep;

    function quote(string) {
        // If the string contains no control characters, no quote characters, and no
        // backslash characters, then we can safely slap some quotes around it.
        // Otherwise we must also replace the offending characters with safe escape
        // sequences.

        escapable.lastIndex = 0;
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
            var c = meta[a];
            return typeof c === 'string' ? c :
                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        }) + '"' : '"' + string + '"';
    }

    function str(key, holder) {
        // Produce a string from holder[key].
        var i,          // The loop counter.
                k,          // The member key.
                v,          // The member value.
                length,
                mind = gap,
                partial,
                value = holder[key];

        // If the value has a toJSON method, call it to obtain a replacement value.
        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

        // If we were called with a replacer function, then call the replacer to
        // obtain a replacement value.
        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

        // What happens next depends on the value's type.
        switch (typeof value) {
            case 'string':
                return quote(value);

            case 'number':
                // JSON numbers must be finite. Encode non-finite numbers as null.
                return isFinite(value) ? String(value) : 'null';

            case 'boolean':
            case 'null':
                // If the value is a boolean or null, convert it to a string. Note:
                // typeof null does not produce 'null'. The case is included here in
                // the remote chance that this gets fixed someday.
                return String(value);

            case 'object':
                if (!value) return 'null';
                gap += indent;
                partial = [];

                // Array.isArray
                if (Object.prototype.toString.apply(value) === '[object Array]') {
                    length = value.length;
                    for (i = 0; i < length; i += 1) {
                        partial[i] = str(i, value) || 'null';
                    }

                    // Join all of the elements together, separated with commas, and
                    // wrap them in brackets.
                    v = partial.length === 0 ? '[]' : gap ?
                            '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
                            '[' + partial.join(',') + ']';
                    gap = mind;
                    return v;
                }

                // If the replacer is an array, use it to select the members to be
                // stringified.
                if (rep && typeof rep === 'object') {
                    length = rep.length;
                    for (i = 0; i < length; i += 1) {
                        k = rep[i];
                        if (typeof k === 'string') {
                            v = str(k, value);
                            if (v) {
                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
                            }
                        }
                    }
                }
                else {
                    // Otherwise, iterate through all of the keys in the object.
                    for (k in value) {
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
                            v = str(k, value);
                            if (v) {
                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
                            }
                        }
                    }
                }

                // Join all of the member texts together, separated with commas,
                // and wrap them in braces.

                v = partial.length === 0 ? '{}' : gap ?
                        '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
                        '{' + partial.join(',') + '}';
                gap = mind;
                return v;
        }
    }

    module.exports = function (value, replacer, space) {
        var i;
        gap = '';
        indent = '';

        // If the space parameter is a number, make an indent string containing that
        // many spaces.
        if (typeof space === 'number') {
            for (i = 0; i < space; i += 1) {
                indent += ' ';
            }
        }
        // If the space parameter is a string, it will be used as the indent string.
        else if (typeof space === 'string') {
            indent = space;
        }

        // If there is a replacer, it must be a function or an array.
        // Otherwise, throw an error.
        rep = replacer;
        if (replacer && typeof replacer !== 'function'
                && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) {
            throw new Error('JSON.stringify');
        }

        // Make a fake root object containing our value under the key of ''.
        // Return the result of stringifying the value.
        return str('', {'': value});
    };

}, {}], 10: [function (require, module, exports) {
    var process = require("__browserify_process");
    var Stream = require('stream')

// through
//
// a stream that does nothing but re-emit the input.
// useful for aggregating a series of changing but not ending streams into one stream)

    exports = module.exports = through
    through.through = through

//create a readable writable stream.

    function through(write, end, opts) {
        write = write || function (data) {
            this.queue(data)
        }
        end = end || function () {
            this.queue(null)
        }

        var ended = false, destroyed = false, buffer = [], _ended = false
        var stream = new Stream()
        stream.readable = stream.writable = true
        stream.paused = false

//  stream.autoPause   = !(opts && opts.autoPause   === false)
        stream.autoDestroy = !(opts && opts.autoDestroy === false)

        stream.write = function (data) {
            write.call(this, data)
            return !stream.paused
        }

        function drain() {
            while (buffer.length && !stream.paused) {
                var data = buffer.shift()
                if (null === data)
                    return stream.emit('end')
                else
                    stream.emit('data', data)
            }
        }

        stream.queue = stream.push = function (data) {
//    console.error(ended)
            if (_ended) return stream
            if (data == null) _ended = true
            buffer.push(data)
            drain()
            return stream
        }

        //this will be registered as the first 'end' listener
        //must call destroy next tick, to make sure we're after any
        //stream piped from here.
        //this is only a problem if end is not emitted synchronously.
        //a nicer way to do this is to make sure this is the last listener for 'end'

        stream.on('end', function () {
            stream.readable = false
            if (!stream.writable && stream.autoDestroy)
                process.nextTick(function () {
                    stream.destroy()
                })
        })

        function _end() {
            stream.writable = false
            end.call(stream)
            if (!stream.readable && stream.autoDestroy)
                stream.destroy()
        }

        stream.end = function (data) {
            if (ended) return
            ended = true
            if (arguments.length) stream.write(data)
            _end() // will emit or queue
            return stream
        }

        stream.destroy = function () {
            if (destroyed) return
            destroyed = true
            ended = true
            buffer.length = 0
            stream.writable = stream.readable = false
            stream.emit('close')
            return stream
        }

        stream.pause = function () {
            if (stream.paused) return
            stream.paused = true
            return stream
        }

        stream.resume = function () {
            if (stream.paused) {
                stream.paused = false
                stream.emit('resume')
            }
            drain()
            //may have become paused again,
            //as drain emits 'data'.
            if (!stream.paused)
                stream.emit('drain')
            return stream
        }
        return stream
    }


}, {"__browserify_process": 18, "stream": 16}], 11: [function (require, module, exports) {
// Extends method
// (taken from http://code.jquery.com/jquery-1.9.0.js)
// Populate the class2type map
    var class2type = {};

    var types = ["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object", "Error"];
    for (var i = 0; i < types.length; i++) {
        var typename = types[i];
        class2type[ "[object " + typename + "]" ] = typename.toLowerCase();
    }

    var core_toString = class2type.toString;
    var core_hasOwn = class2type.hasOwnProperty;

    var type = function (obj) {
        if (obj === null) {
            return String(obj);
        }
        return typeof obj === "object" || typeof obj === "function" ?
                class2type[core_toString.call(obj)] || "object" :
                typeof obj;
    };

    var isWindow = function (obj) {
        return obj !== null && obj === obj.window;
    };

    var isPlainObject = function (obj) {
        // Must be an Object.
        // Because of IE, we also have to check the presence of the constructor property.
        // Make sure that DOM nodes and window objects don't pass through, as well
        if (!obj || type(obj) !== "object" || obj.nodeType || isWindow(obj)) {
            return false;
        }

        try {
            // Not own constructor property must be Object
            if (obj.constructor && !core_hasOwn.call(obj, "constructor") && !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
                return false;
            }
        } catch (e) {
            // IE8,9 Will throw exceptions on certain host objects #9897
            return false;
        }

        // Own properties are enumerated firstly, so to speed up,
        // if last one is own, then all properties are own.

        var key;
        for (key in obj) {
        }

        return key === undefined || core_hasOwn.call(obj, key);
    };

    var isFunction = function (obj) {
        return type(obj) === "function";
    };

    var isArray = Array.isArray || function (obj) {
        return type(obj) === "array";
    };

    var extend = function () {
        var options, name, src, copy, copyIsArray, clone,
                target = arguments[0] || {},
                i = 1,
                length = arguments.length,
                deep = false;

        // Handle a deep copy situation
        if (typeof target === "boolean") {
            deep = target;
            target = arguments[1] || {};
            // skip the boolean and the target
            i = 2;
        }

        // Handle case when target is a string or something (possible in deep copy)
        if (typeof target !== "object" && !isFunction(target)) {
            target = {};
        }

        // extend jQuery itself if only one argument is passed
        if (length === i) {
            target = this;
            --i;
        }

        for (; i < length; i++) {
            // Only deal with non-null/undefined values
            if ((options = arguments[ i ]) != null) {
                // Extend the base object
                for (name in options) {
                    src = target[ name ];
                    copy = options[ name ];

                    // Prevent never-ending loop
                    if (target === copy) {
                        continue;
                    }

                    // Recurse if we're merging plain objects or arrays
                    if (deep && copy && ( isPlainObject(copy) || (copyIsArray = isArray(copy)) )) {
                        if (copyIsArray) {
                            copyIsArray = false;
                            clone = src && isArray(src) ? src : [];

                        } else {
                            clone = src && isPlainObject(src) ? src : {};
                        }

                        // Never move original objects, clone them
                        target[ name ] = extend(deep, clone, copy);

                        // Don't bring in undefined values
                    } else if (copy !== undefined) {
                        if (!(isArray(options) && isFunction(copy))) {
                            target[ name ] = copy;
                        }
                    }
                }
            }
        }

        // Return the modified object
        return target;
    };

    if (typeof module !== 'undefined' && module.exports) {
        module.exports = extend;
    }

}, {}], 12: [function (require, module, exports) {
    'use strict';

    var extend;
    if (typeof module !== 'undefined' && module.exports) {
        extend = require('./deps/extend');
    }


// for a better overview of what this is doing, read:
// https://github.com/apache/couchdb/blob/master/src/couchdb/couch_key_tree.erl
//
// But for a quick intro, CouchDB uses a revision tree to store a documents
// history, A -> B -> C, when a document has conflicts, that is a branch in the
// tree, A -> (B1 | B2 -> C), We store these as a nested array in the format
//
// KeyTree = [Path ... ]
// Path = {pos: position_from_root, ids: Tree}
// Tree = [Key, Opts, [Tree, ...]], in particular single node: [Key, []]

// Turn a path as a flat array into a tree with a single branch
    function pathToTree(path) {
        var doc = path.shift();
        var root = [doc.id, doc.opts, []];
        var leaf = root;
        var nleaf;

        while (path.length) {
            doc = path.shift();
            nleaf = [doc.id, doc.opts, []];
            leaf[2].push(nleaf);
            leaf = nleaf;
        }
        return root;
    }

// Merge two trees together
// The roots of tree1 and tree2 must be the same revision
    function mergeTree(in_tree1, in_tree2) {
        var queue = [
            {tree1: in_tree1, tree2: in_tree2}
        ];
        var conflicts = false;
        while (queue.length > 0) {
            var item = queue.pop();
            var tree1 = item.tree1;
            var tree2 = item.tree2;

            if (tree1[1].status || tree2[1].status) {
                tree1[1].status = (tree1[1].status === 'available' ||
                        tree2[1].status === 'available') ? 'available' : 'missing';
            }

            for (var i = 0; i < tree2[2].length; i++) {
                if (!tree1[2][0]) {
                    conflicts = 'new_leaf';
                    tree1[2][0] = tree2[2][i];
                    continue;
                }

                var merged = false;
                for (var j = 0; j < tree1[2].length; j++) {
                    if (tree1[2][j][0] === tree2[2][i][0]) {
                        queue.push({tree1: tree1[2][j], tree2: tree2[2][i]});
                        merged = true;
                    }
                }
                if (!merged) {
                    conflicts = 'new_branch';
                    tree1[2].push(tree2[2][i]);
                    tree1[2].sort();
                }
            }
        }
        return {conflicts: conflicts, tree: in_tree1};
    }

    function doMerge(tree, path, dontExpand) {
        var restree = [];
        var conflicts = false;
        var merged = false;
        var res, branch;

        if (!tree.length) {
            return {tree: [path], conflicts: 'new_leaf'};
        }

        tree.forEach(function (branch) {
            if (branch.pos === path.pos && branch.ids[0] === path.ids[0]) {
                // Paths start at the same position and have the same root, so they need
                // merged
                res = mergeTree(branch.ids, path.ids);
                restree.push({pos: branch.pos, ids: res.tree});
                conflicts = conflicts || res.conflicts;
                merged = true;
            } else if (dontExpand !== true) {
                // The paths start at a different position, take the earliest path and
                // traverse up until it as at the same point from root as the path we want to
                // merge.  If the keys match we return the longer path with the other merged
                // After stemming we dont want to expand the trees

                var t1 = branch.pos < path.pos ? branch : path;
                var t2 = branch.pos < path.pos ? path : branch;
                var diff = t2.pos - t1.pos;

                var candidateParents = [];

                var trees = [];
                trees.push({ids: t1.ids, diff: diff, parent: null, parentIdx: null});
                while (trees.length > 0) {
                    var item = trees.pop();
                    if (item.diff === 0) {
                        if (item.ids[0] === t2.ids[0]) {
                            candidateParents.push(item);
                        }
                        continue;
                    }
                    if (!item.ids) {
                        continue;
                    }
                    /*jshint loopfunc:true */
                    item.ids[2].forEach(function (el, idx) {
                        trees.push({ids: el, diff: item.diff - 1, parent: item.ids, parentIdx: idx});
                    });
                }

                var el = candidateParents[0];

                if (!el) {
                    restree.push(branch);
                } else {
                    res = mergeTree(el.ids, t2.ids);
                    el.parent[2][el.parentIdx] = res.tree;
                    restree.push({pos: t1.pos, ids: t1.ids});
                    conflicts = conflicts || res.conflicts;
                    merged = true;
                }
            } else {
                restree.push(branch);
            }
        });

        // We didnt find
        if (!merged) {
            restree.push(path);
        }

        restree.sort(function (a, b) {
            return a.pos - b.pos;
        });

        return {
            tree: restree,
            conflicts: conflicts || 'internal_node'
        };
    }

// To ensure we dont grow the revision tree infinitely, we stem old revisions
    function stem(tree, depth) {
        // First we break out the tree into a complete list of root to leaf paths,
        // we cut off the start of the path and generate a new set of flat trees
        var stemmedPaths = PouchMerge.rootToLeaf(tree).map(function (path) {
            var stemmed = path.ids.slice(-depth);
            return {
                pos: path.pos + (path.ids.length - stemmed.length),
                ids: pathToTree(stemmed)
            };
        });
        // Then we remerge all those flat trees together, ensuring that we dont
        // connect trees that would go beyond the depth limit
        return stemmedPaths.reduce(function (prev, current, i, arr) {
            return doMerge(prev, current, true).tree;
        }, [stemmedPaths.shift()]);
    }

    var PouchMerge = {};

    PouchMerge.merge = function (tree, path, depth) {
        // Ugh, nicer way to not modify arguments in place?
        tree = extend(true, [], tree);
        path = extend(true, {}, path);
        var newTree = doMerge(tree, path);
        return {
            tree: stem(newTree.tree, depth),
            conflicts: newTree.conflicts
        };
    };

// We fetch all leafs of the revision tree, and sort them based on tree length
// and whether they were deleted, undeleted documents with the longest revision
// tree (most edits) win
// The final sort algorithm is slightly documented in a sidebar here:
// http://guide.couchdb.org/draft/conflicts.html
    PouchMerge.winningRev = function (metadata) {
        var leafs = [];
        PouchMerge.traverseRevTree(metadata.rev_tree,
                function (isLeaf, pos, id, something, opts) {
                    if (isLeaf) {
                        leafs.push({pos: pos, id: id, deleted: !!opts.deleted});
                    }
                });
        leafs.sort(function (a, b) {
            if (a.deleted !== b.deleted) {
                return a.deleted > b.deleted ? 1 : -1;
            }
            if (a.pos !== b.pos) {
                return b.pos - a.pos;
            }
            return a.id < b.id ? 1 : -1;
        });

        return leafs[0].pos + '-' + leafs[0].id;
    };

// Pretty much all below can be combined into a higher order function to
// traverse revisions
// The return value from the callback will be passed as context to all
// children of that node
    PouchMerge.traverseRevTree = function (revs, callback) {
        var toVisit = [];

        revs.forEach(function (tree) {
            toVisit.push({pos: tree.pos, ids: tree.ids});
        });
        while (toVisit.length > 0) {
            var node = toVisit.pop();
            var pos = node.pos;
            var tree = node.ids;
            var newCtx = callback(tree[2].length === 0, pos, tree[0], node.ctx, tree[1]);
            /*jshint loopfunc: true */
            tree[2].forEach(function (branch) {
                toVisit.push({pos: pos + 1, ids: branch, ctx: newCtx});
            });
        }
    };

    PouchMerge.collectLeaves = function (revs) {
        var leaves = [];
        PouchMerge.traverseRevTree(revs, function (isLeaf, pos, id, acc, opts) {
            if (isLeaf) {
                leaves.unshift({rev: pos + "-" + id, pos: pos, opts: opts});
            }
        });
        leaves.sort(function (a, b) {
            return b.pos - a.pos;
        });
        leaves.map(function (leaf) {
            delete leaf.pos;
        });
        return leaves;
    };

// returns revs of all conflicts that is leaves such that
// 1. are not deleted and
// 2. are different than winning revision
    PouchMerge.collectConflicts = function (metadata) {
        var win = PouchMerge.winningRev(metadata);
        var leaves = PouchMerge.collectLeaves(metadata.rev_tree);
        var conflicts = [];
        leaves.forEach(function (leaf) {
            if (leaf.rev !== win && !leaf.opts.deleted) {
                conflicts.push(leaf.rev);
            }
        });
        return conflicts;
    };

    PouchMerge.rootToLeaf = function (tree) {
        var paths = [];
        PouchMerge.traverseRevTree(tree, function (isLeaf, pos, id, history, opts) {
            history = history ? history.slice(0) : [];
            history.push({id: id, opts: opts});
            if (isLeaf) {
                var rootPos = pos + 1 - history.length;
                paths.unshift({pos: rootPos, ids: history});
            }
            return history;
        });
        return paths;
    };

// a few hacks to get things in the right place for node.js
    if (typeof module !== 'undefined' && module.exports) {
        module.exports = PouchMerge;
    }
}, {"./deps/extend": 11}], 13: [function (require, module, exports) {
    /*globals require, test: true */

    'use strict';

    var test = require('tape');
    var PouchMerge = require('../../src/pouch.merge.js');

    var merge = PouchMerge.merge;
    var winningRev = PouchMerge.winningRev;

// Set of predefined trees used in various tests
    var one = {pos: 1, ids: ['1', {}, []]};
    var two = {pos: 1, ids: ['2', {}, []]};
    var twoSibs = [one, two];
    var three = {pos: 1, ids: ['3', {}, []]};
    var threeSibs = [one, two, three];
    var stemmed1b = {pos: 2, ids: ['1a', {}, []]};
    var stemmed1bb = {pos: 3, ids: ['1bb', {}, []]};
    var stemmed1aa = {pos: 3, ids: ['1aa', {}, []]};
    var stemmed1a = {pos: 2, ids: ['1a', {}, [
        ['1aa', {}, []]
    ]]};
    var oneChild = {pos: 1, ids: ['1', {}, [
        ['1a', {}, []]
    ]]};

    var simple = {
        pos: 1,
        ids: ['1', {}, []]
    };

    var two0 = {
        pos: 1,
        ids: ['1', {}, [
            ['2_0', {}, []]
        ]]
    };

    var two1 = {
        pos: 1,
        ids: ['1', {}, [
            ['2_1', {}, []]
        ]]
    };

    var newleaf = {
        pos: 2, ids: ['2_0', {}, [
            ['3', {}, []]
        ]]
    };

    var withnewleaf = {
        pos: 1,
        ids: ['1', {}, [
            ['2_0', {}, [
                ['3', {}, []]
            ]]
        ]]
    };

    var newbranch = {
        pos: 1,
        ids: ['1', {}, [
            ['2_0', {}, []],
            ['2_1', {}, []]
        ]]
    };

    var newdeepbranch = {
        pos: 2, ids: ['2_0', {}, [
            ['3_1', {}, []]
        ]]
    };

    var stemmededit = {
        pos: 3, ids: ['3', {}, []]
    };

    var stemmedconflicts = [simple, stemmededit];

    var newbranchleaf = {
        pos: 1,
        ids: ['1', {}, [
            ['2_0', {}, [
                ['3', {}, []]
            ]],
            ['2_1', {}, []]
        ]]
    };

    var newbranchleafbranch = {
        pos: 1,
        ids: ['1', {}, [
            ['2_0', {}, [
                ['3', {}, []],
                ['3_1', {}, []]
            ]],
            ['2_1', {}, []]
        ]]
    };

    var stemmed2 = [
        {pos: 1, ids: ['1', {}, [
            ['2_1', {}, []]
        ]]},
        {pos: 2, ids: ['2_0', {}, [
            ['3', {}, []],
            ['3_1', {}, []]
        ]]}
    ];

    var stemmed3 = [
        {pos: 2, ids: ['2_1', {}, []]},
        {pos: 3, ids: ['3', {}, []]},
        {pos: 3, ids: ['3_1', {}, []]}
    ];

    var partialrecover = [
        {pos: 1, ids: ['1', {}, [
            ['2_0', {}, [
                ['3', {}, []]
            ]]
        ]]},
        {pos: 2, ids: ['2_1', {}, []]},
        {pos: 3, ids: ['3_1', {}, []]}
    ];

    var tree1 = [
        {"pos": 1, "ids": [
            "bfe70372c90ded1087239e5191984f76", {}, [
                ["44d71a718b90e4696c06a90e08912c8f", {}, []],
                ["56e657612d55ab1a402dcb281c874f2a", {}, [
                    ["93c3db16462f656f7172ccabd3cf6cd6", {}, []]
                ]]
            ]]
        }
    ];

// this one is from issue #293
    var tree2 = [
        {"pos": 1, "ids": [
            "203db1a1810a838895d561f67b224b5d", {}, [
                ["bf5e08a4f9fa6d33a53f4a00ae3ea399", {}, [
                    ["28cd77a3ca30f79e1cfffcd6a41ca308", {}, []]
                ]]
            ]
        ]},
        {"pos": 1, "ids": [
            "c6d5cce35bcfbef90b20f140d723cbdb", {}, [
                ["1b8dfbb1267e213328920bae43f2f597", {}, []],
                ["59ed830b84b276ab776c3c51aaf93a16", {}, [
                    ["64a9842c6aea50bf24660378e496e853", {}, []]
                ]]
            ]]
        }
    ];

    var twoChild = {pos: 1, ids: ['1', {}, [
        ['1a', {}, [
            ['1aa', {}, []]
        ]]
    ]]};

    var twoChildSibs = {pos: 1, ids: ['1', {}, [
        ['1a', {}, []],
        ['1b', {}, []]
    ]]};

    var twoChildPlusSibs = {pos: 1, ids: ['1', {}, [
        ['1a', {}, [
            ['1aa', {}, []]
        ]],
        ['1b', {}, []]
    ]]};

    var twoChildPlusSibs2 = {pos: 1, ids: ['1', {}, [
        ['1a', {}, []],
        ['1b', {}, [
            ['1bb', {}, []]
        ]]
    ]]};

    var stemmedTwoChildSibs2 = [
        {pos: 2, ids: ['1a', {}, []]},
        {pos: 2, ids: ['1b', {}, [
            ['1bb', {}, []]
        ]]}
    ];

    var foo = {pos: 1, ids: ['foo', {}, [
        ['foo2', {}, []],
        ['foo3', {}, []]
    ]]};

    var bar = {pos: 1, ids: ['foo', {}, [
        ['foo3', {}, [
            ['foo4', {}, []]
        ]]
    ]]};

    var fooBar = {pos: 1, ids: ['foo', {}, [
        ['foo2', {}, []],
        ['foo3', {}, [
            ['foo4', {}, []]
        ]]
    ]]};


    test('Test Revision tree merging', function (t) {

        t.plan(33);

        // Tests from:
        // https://github.com/davisp/couchdb/blob/local_doc_revs/test/etap/060-kt-merging.t

        t.deepEqual(merge([], simple, 10), {
            tree: [simple],
            conflicts: 'new_leaf'
        }, 'Merging a path into an empty tree is the path');

        t.deepEqual(merge([simple], simple, 10), {
            tree: [simple],
            conflicts: 'internal_node'
        }, 'Remerge path into path is reflexive');

        t.deepEqual(merge([], two0, 10), {
            tree: [two0],
            conflicts: 'new_leaf'
        }, 'Merging a path with multiple entries is the path');

        t.deepEqual(merge([two0], two0, 10), {
            tree: [two0],
            conflicts: 'internal_node'
        }, 'Merging a path with multiple entries is reflexive');

        t.deepEqual(merge([two0], simple, 10), {
            tree: [two0],
            conflicts: 'internal_node'
        }, 'Merging a subpath into a path results in the path');

        t.deepEqual(merge([two0], newleaf, 10), {
            tree: [withnewleaf],
            conflicts: 'new_leaf'
        }, 'Merging a new leaf gives us a new leaf');

        t.deepEqual(merge([two0], two1, 10), {
            tree: [newbranch],
            conflicts: 'new_branch'
        }, 'Merging a new branch returns a proper tree');

        t.deepEqual(merge([two1], two0, 10), {
            tree: [newbranch],
            conflicts: 'new_branch'
        }, 'Order of merging does not affect the resulting tree');

        t.deepEqual(merge([newbranch], newleaf, 10), {
            tree: [newbranchleaf],
            conflicts: 'new_leaf'
        }, 'Merging a new_leaf doesnt return new_branch when branches exist');

        t.deepEqual(merge([newbranchleaf], newdeepbranch, 10), {
            tree: [newbranchleafbranch],
            conflicts: 'new_branch'
        }, 'Merging a deep branch with branches works');

        t.deepEqual(merge(stemmedconflicts, withnewleaf, 10), {
            tree: [withnewleaf],
            conflicts: 'new_leaf'
        }, 'New information reconnects steming induced conflicts');

        t.deepEqual(merge([two0], newleaf, 2), {
            tree: [newleaf],
            conflicts: 'new_leaf'
        }, 'Simple stemming works');

        t.deepEqual(merge([newbranchleafbranch], simple, 2), {
            tree: stemmed2,
            conflicts: 'internal_node'
        }, 'Merge with stemming works correctly for branches');

        t.deepEqual(merge([newbranchleafbranch], simple, 1), {
            tree: stemmed3,
            conflicts: 'internal_node'
        }, 'Merge with stemming to leaves works fine');

        t.deepEqual(merge(stemmed3, withnewleaf, 10), {
            tree: partialrecover,
            conflicts: 'internal_node'
        }, 'Merging unstemmed recovers as much as possible without losing info');

        t.equal(winningRev({rev_tree: tree1}),
                "3-93c3db16462f656f7172ccabd3cf6cd6",
                "Picks the longest path");

        t.equal(winningRev({rev_tree: tree2}),
                "3-64a9842c6aea50bf24660378e496e853",
                "Picks the longest path");

        // Tests from:
        // https://github.com/apache/couchdb/blob/master/test/etap/060-kt-merging.t

        t.deepEqual(merge([], one, 10), {
            tree: [one],
            conflicts: 'new_leaf'
        }, 'The empty tree is the identity for merge.');

        t.deepEqual(merge([one], one, 10), {
            tree: [one],
            conflicts: 'internal_node'
        }, 'Merging is reflexive');

        t.deepEqual(merge(twoSibs, one, 10), {
            tree: twoSibs,
            conflicts: 'internal_node'
        }, 'Merging a prefix of a tree with the tree yields the tree.');

        t.deepEqual(merge(twoSibs, three, 10), {
            tree: threeSibs,
            conflicts: 'internal_node'
        }, 'Merging a third unrelated branch leads to a conflict.');

        t.deepEqual(merge([twoChild], twoChild, 10), {
            tree: [twoChild],
            conflicts: 'internal_node'
        }, 'Merging two children is still reflexive.');

        t.deepEqual(merge([twoChildSibs], twoChildSibs, 10), {
            tree: [twoChildSibs],
            conflicts: 'internal_node'
        }, 'Merging a tree to itself is itself.');

        t.deepEqual(merge([twoChild], twoChildSibs, 10), {
            tree: [twoChildPlusSibs],
            conflicts: 'new_branch'
        }, 'Merging tree of uneven length at node 2.');

        t.deepEqual(merge([twoChildSibs], stemmed1b, 10), {
            tree: [twoChildSibs],
            conflicts: 'internal_node'
        }, 'Merging a tree with a stem.');

        t.deepEqual(merge([twoChildPlusSibs2], stemmed1bb, 10), {
            tree: [twoChildPlusSibs2],
            conflicts: 'internal_node'
        }, 'Merging a stem at a deeper level.');

        t.deepEqual(merge(stemmedTwoChildSibs2, stemmed1bb, 10), {
            tree: stemmedTwoChildSibs2,
            conflicts: 'internal_node'
        }, 'Merging a stem at a deeper level against paths at deeper levels.');

        t.deepEqual(merge([twoChild], stemmed1aa, 10), {
            tree: [twoChild],
            conflicts: 'internal_node'
        }, 'Merging a stem at a deeper level against paths at deeper levels.');

        t.deepEqual(merge([twoChild], stemmed1a, 10), {
            tree: [twoChild],
            conflicts: 'internal_node'
        }, 'Merging a larger stem.');

        t.deepEqual(merge([stemmed1a], stemmed1aa, 10), {
            tree: [stemmed1a],
            conflicts: 'internal_node'
        }, 'More merging.');

        t.deepEqual(merge([oneChild], stemmed1aa, 10), {
            tree: [oneChild, stemmed1aa],
            conflicts: 'internal_node'
        }, 'Merging should create conflicts.');

        t.deepEqual(merge([oneChild, stemmed1aa], twoChild, 10), {
            tree: [twoChild],
            conflicts: 'new_leaf'
        }, 'Merging should create conflicts.');

        t.deepEqual(merge([foo], bar, 10), {
            tree: [fooBar],
            conflicts: 'new_leaf'
        }, 'Merging trees with conflicts ought to behave.');

    });

}, {"../../src/pouch.merge.js": 12, "tape": 1}], 14: [function (require, module, exports) {
    var process = require("__browserify_process");
    if (!process.EventEmitter) process.EventEmitter = function () {
    };

    var EventEmitter = exports.EventEmitter = process.EventEmitter;
    var isArray = typeof Array.isArray === 'function'
                    ? Array.isArray
                    : function (xs) {
                return Object.prototype.toString.call(xs) === '[object Array]'
            }
            ;

    function indexOf(xs, x) {
        if (xs.indexOf) return xs.indexOf(x);
        for (var i = 0; i < xs.length; i++) {
            if (x === xs[i]) return i;
        }
        return -1;
    }

// By default EventEmitters will print a warning if more than
// 10 listeners are added to it. This is a useful default which
// helps finding memory leaks.
//
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
    var defaultMaxListeners = 10;
    EventEmitter.prototype.setMaxListeners = function (n) {
        if (!this._events) this._events = {};
        this._events.maxListeners = n;
    };


    EventEmitter.prototype.emit = function (type) {
        // If there is no 'error' event listener then throw.
        if (type === 'error') {
            if (!this._events || !this._events.error ||
                    (isArray(this._events.error) && !this._events.error.length)) {
                if (arguments[1] instanceof Error) {
                    throw arguments[1]; // Unhandled 'error' event
                } else {
                    throw new Error("Uncaught, unspecified 'error' event.");
                }
                return false;
            }
        }

        if (!this._events) return false;
        var handler = this._events[type];
        if (!handler) return false;

        if (typeof handler == 'function') {
            switch (arguments.length) {
                // fast cases
                case 1:
                    handler.call(this);
                    break;
                case 2:
                    handler.call(this, arguments[1]);
                    break;
                case 3:
                    handler.call(this, arguments[1], arguments[2]);
                    break;
                // slower
                default:
                    var args = Array.prototype.slice.call(arguments, 1);
                    handler.apply(this, args);
            }
            return true;

        } else if (isArray(handler)) {
            var args = Array.prototype.slice.call(arguments, 1);

            var listeners = handler.slice();
            for (var i = 0, l = listeners.length; i < l; i++) {
                listeners[i].apply(this, args);
            }
            return true;

        } else {
            return false;
        }
    };

// EventEmitter is defined in src/node_events.cc
// EventEmitter.prototype.emit() is also defined there.
    EventEmitter.prototype.addListener = function (type, listener) {
        if ('function' !== typeof listener) {
            throw new Error('addListener only takes instances of Function');
        }

        if (!this._events) this._events = {};

        // To avoid recursion in the case that type == "newListeners"! Before
        // adding it to the listeners, first emit "newListeners".
        this.emit('newListener', type, listener);

        if (!this._events[type]) {
            // Optimize the case of one listener. Don't need the extra array object.
            this._events[type] = listener;
        } else if (isArray(this._events[type])) {

            // Check for listener leak
            if (!this._events[type].warned) {
                var m;
                if (this._events.maxListeners !== undefined) {
                    m = this._events.maxListeners;
                } else {
                    m = defaultMaxListeners;
                }

                if (m && m > 0 && this._events[type].length > m) {
                    this._events[type].warned = true;
                    console.error('(node) warning: possible EventEmitter memory ' +
                            'leak detected. %d listeners added. ' +
                            'Use emitter.setMaxListeners() to increase limit.',
                            this._events[type].length);
                    console.trace();
                }
            }

            // If we've already got an array, just append.
            this._events[type].push(listener);
        } else {
            // Adding the second element, need to change to array.
            this._events[type] = [this._events[type], listener];
        }

        return this;
    };

    EventEmitter.prototype.on = EventEmitter.prototype.addListener;

    EventEmitter.prototype.once = function (type, listener) {
        var self = this;
        self.on(type, function g() {
            self.removeListener(type, g);
            listener.apply(this, arguments);
        });

        return this;
    };

    EventEmitter.prototype.removeListener = function (type, listener) {
        if ('function' !== typeof listener) {
            throw new Error('removeListener only takes instances of Function');
        }

        // does not use listeners(), so no side effect of creating _events[type]
        if (!this._events || !this._events[type]) return this;

        var list = this._events[type];

        if (isArray(list)) {
            var i = indexOf(list, listener);
            if (i < 0) return this;
            list.splice(i, 1);
            if (list.length == 0)
                delete this._events[type];
        } else if (this._events[type] === listener) {
            delete this._events[type];
        }

        return this;
    };

    EventEmitter.prototype.removeAllListeners = function (type) {
        if (arguments.length === 0) {
            this._events = {};
            return this;
        }

        // does not use listeners(), so no side effect of creating _events[type]
        if (type && this._events && this._events[type]) this._events[type] = null;
        return this;
    };

    EventEmitter.prototype.listeners = function (type) {
        if (!this._events) this._events = {};
        if (!this._events[type]) this._events[type] = [];
        if (!isArray(this._events[type])) {
            this._events[type] = [this._events[type]];
        }
        return this._events[type];
    };

    EventEmitter.listenerCount = function (emitter, type) {
        var ret;
        if (!emitter._events || !emitter._events[type])
            ret = 0;
        else if (typeof emitter._events[type] === 'function')
            ret = 1;
        else
            ret = emitter._events[type].length;
        return ret;
    };

}, {"__browserify_process": 18}], 15: [function (require, module, exports) {
    var process = require("__browserify_process");

    function filter(xs, fn) {
        var res = [];
        for (var i = 0; i < xs.length; i++) {
            if (fn(xs[i], i, xs)) res.push(xs[i]);
        }
        return res;
    }

// resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
    function normalizeArray(parts, allowAboveRoot) {
        // if the path tries to go above the root, `up` ends up > 0
        var up = 0;
        for (var i = parts.length; i >= 0; i--) {
            var last = parts[i];
            if (last == '.') {
                parts.splice(i, 1);
            } else if (last === '..') {
                parts.splice(i, 1);
                up++;
            } else if (up) {
                parts.splice(i, 1);
                up--;
            }
        }

        // if the path is allowed to go above the root, restore leading ..s
        if (allowAboveRoot) {
            for (; up--; up) {
                parts.unshift('..');
            }
        }

        return parts;
    }

// Regex to split a filename into [*, dir, basename, ext]
// posix version
    var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;

// path.resolve([from ...], to)
// posix version
    exports.resolve = function () {
        var resolvedPath = '',
                resolvedAbsolute = false;

        for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
            var path = (i >= 0)
                    ? arguments[i]
                    : process.cwd();

            // Skip empty and invalid entries
            if (typeof path !== 'string' || !path) {
                continue;
            }

            resolvedPath = path + '/' + resolvedPath;
            resolvedAbsolute = path.charAt(0) === '/';
        }

// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)

// Normalize the path
        resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function (p) {
            return !!p;
        }), !resolvedAbsolute).join('/');

        return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
    };

// path.normalize(path)
// posix version
    exports.normalize = function (path) {
        var isAbsolute = path.charAt(0) === '/',
                trailingSlash = path.slice(-1) === '/';

// Normalize the path
        path = normalizeArray(filter(path.split('/'), function (p) {
            return !!p;
        }), !isAbsolute).join('/');

        if (!path && !isAbsolute) {
            path = '.';
        }
        if (path && trailingSlash) {
            path += '/';
        }

        return (isAbsolute ? '/' : '') + path;
    };


// posix version
    exports.join = function () {
        var paths = Array.prototype.slice.call(arguments, 0);
        return exports.normalize(filter(paths,function (p, index) {
            return p && typeof p === 'string';
        }).join('/'));
    };


    exports.dirname = function (path) {
        var dir = splitPathRe.exec(path)[1] || '';
        var isWindows = false;
        if (!dir) {
            // No dirname
            return '.';
        } else if (dir.length === 1 ||
                (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
            // It is just a slash or a drive letter with a slash
            return dir;
        } else {
            // It is a full dirname, strip trailing slash
            return dir.substring(0, dir.length - 1);
        }
    };


    exports.basename = function (path, ext) {
        var f = splitPathRe.exec(path)[2] || '';
        // TODO: make this comparison case-insensitive on windows?
        if (ext && f.substr(-1 * ext.length) === ext) {
            f = f.substr(0, f.length - ext.length);
        }
        return f;
    };


    exports.extname = function (path) {
        return splitPathRe.exec(path)[3] || '';
    };

    exports.relative = function (from, to) {
        from = exports.resolve(from).substr(1);
        to = exports.resolve(to).substr(1);

        function trim(arr) {
            var start = 0;
            for (; start < arr.length; start++) {
                if (arr[start] !== '') break;
            }

            var end = arr.length - 1;
            for (; end >= 0; end--) {
                if (arr[end] !== '') break;
            }

            if (start > end) return [];
            return arr.slice(start, end - start + 1);
        }

        var fromParts = trim(from.split('/'));
        var toParts = trim(to.split('/'));

        var length = Math.min(fromParts.length, toParts.length);
        var samePartsLength = length;
        for (var i = 0; i < length; i++) {
            if (fromParts[i] !== toParts[i]) {
                samePartsLength = i;
                break;
            }
        }

        var outputParts = [];
        for (var i = samePartsLength; i < fromParts.length; i++) {
            outputParts.push('..');
        }

        outputParts = outputParts.concat(toParts.slice(samePartsLength));

        return outputParts.join('/');
    };

    exports.sep = '/';

}, {"__browserify_process": 18}], 16: [function (require, module, exports) {
    var events = require('events');
    var util = require('util');

    function Stream() {
        events.EventEmitter.call(this);
    }

    util.inherits(Stream, events.EventEmitter);
    module.exports = Stream;
// Backwards-compat with node 0.4.x
    Stream.Stream = Stream;

    Stream.prototype.pipe = function (dest, options) {
        var source = this;

        function ondata(chunk) {
            if (dest.writable) {
                if (false === dest.write(chunk) && source.pause) {
                    source.pause();
                }
            }
        }

        source.on('data', ondata);

        function ondrain() {
            if (source.readable && source.resume) {
                source.resume();
            }
        }

        dest.on('drain', ondrain);

        // If the 'end' option is not supplied, dest.end() will be called when
        // source gets the 'end' or 'close' events.  Only dest.end() once, and
        // only when all sources have ended.
        if (!dest._isStdio && (!options || options.end !== false)) {
            dest._pipeCount = dest._pipeCount || 0;
            dest._pipeCount++;

            source.on('end', onend);
            source.on('close', onclose);
        }

        var didOnEnd = false;

        function onend() {
            if (didOnEnd) return;
            didOnEnd = true;

            dest._pipeCount--;

            // remove the listeners
            cleanup();

            if (dest._pipeCount > 0) {
                // waiting for other incoming streams to end.
                return;
            }

            dest.end();
        }


        function onclose() {
            if (didOnEnd) return;
            didOnEnd = true;

            dest._pipeCount--;

            // remove the listeners
            cleanup();

            if (dest._pipeCount > 0) {
                // waiting for other incoming streams to end.
                return;
            }

            dest.destroy();
        }

        // don't leave dangling pipes when there are errors.
        function onerror(er) {
            cleanup();
            if (this.listeners('error').length === 0) {
                throw er; // Unhandled stream error in pipe.
            }
        }

        source.on('error', onerror);
        dest.on('error', onerror);

        // remove all the event listeners that were added.
        function cleanup() {
            source.removeListener('data', ondata);
            dest.removeListener('drain', ondrain);

            source.removeListener('end', onend);
            source.removeListener('close', onclose);

            source.removeListener('error', onerror);
            dest.removeListener('error', onerror);

            source.removeListener('end', cleanup);
            source.removeListener('close', cleanup);

            dest.removeListener('end', cleanup);
            dest.removeListener('close', cleanup);
        }

        source.on('end', cleanup);
        source.on('close', cleanup);

        dest.on('end', cleanup);
        dest.on('close', cleanup);

        dest.emit('pipe', source);

        // Allow for unix-like usage: A.pipe(B).pipe(C)
        return dest;
    };

}, {"events": 14, "util": 17}], 17: [function (require, module, exports) {
    var events = require('events');

    exports.isArray = isArray;
    exports.isDate = function (obj) {
        return Object.prototype.toString.call(obj) === '[object Date]'
    };
    exports.isRegExp = function (obj) {
        return Object.prototype.toString.call(obj) === '[object RegExp]'
    };


    exports.print = function () {
    };
    exports.puts = function () {
    };
    exports.debug = function () {
    };

    exports.inspect = function (obj, showHidden, depth, colors) {
        var seen = [];

        var stylize = function (str, styleType) {
            // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
            var styles =
            { 'bold': [1, 22],
                'italic': [3, 23],
                'underline': [4, 24],
                'inverse': [7, 27],
                'white': [37, 39],
                'grey': [90, 39],
                'black': [30, 39],
                'blue': [34, 39],
                'cyan': [36, 39],
                'green': [32, 39],
                'magenta': [35, 39],
                'red': [31, 39],
                'yellow': [33, 39] };

            var style =
                    { 'special': 'cyan',
                        'number': 'blue',
                        'boolean': 'yellow',
                        'undefined': 'grey',
                        'null': 'bold',
                        'string': 'green',
                        'date': 'magenta',
                        // "name": intentionally not styling
                        'regexp': 'red' }[styleType];

            if (style) {
                return '\u001b[' + styles[style][0] + 'm' + str +
                        '\u001b[' + styles[style][1] + 'm';
            } else {
                return str;
            }
        };
        if (!colors) {
            stylize = function (str, styleType) {
                return str;
            };
        }

        function format(value, recurseTimes) {
            // Provide a hook for user-specified inspect functions.
            // Check that value is an object with an inspect function on it
            if (value && typeof value.inspect === 'function' &&
                // Filter out the util module, it's inspect function is special
                    value !== exports &&
                // Also filter out any prototype objects using the circular check.
                    !(value.constructor && value.constructor.prototype === value)) {
                return value.inspect(recurseTimes);
            }

            // Primitive types cannot have properties
            switch (typeof value) {
                case 'undefined':
                    return stylize('undefined', 'undefined');

                case 'string':
                    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                            .replace(/'/g, "\\'")
                            .replace(/\\"/g, '"') + '\'';
                    return stylize(simple, 'string');

                case 'number':
                    return stylize('' + value, 'number');

                case 'boolean':
                    return stylize('' + value, 'boolean');
            }
            // For some reason typeof null is "object", so special case here.
            if (value === null) {
                return stylize('null', 'null');
            }

            // Look up the keys of the object.
            var visible_keys = Object_keys(value);
            var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys;

            // Functions without properties can be shortcutted.
            if (typeof value === 'function' && keys.length === 0) {
                if (isRegExp(value)) {
                    return stylize('' + value, 'regexp');
                } else {
                    var name = value.name ? ': ' + value.name : '';
                    return stylize('[Function' + name + ']', 'special');
                }
            }

            // Dates without properties can be shortcutted
            if (isDate(value) && keys.length === 0) {
                return stylize(value.toUTCString(), 'date');
            }

            var base, type, braces;
            // Determine the object type
            if (isArray(value)) {
                type = 'Array';
                braces = ['[', ']'];
            } else {
                type = 'Object';
                braces = ['{', '}'];
            }

            // Make functions say that they are functions
            if (typeof value === 'function') {
                var n = value.name ? ': ' + value.name : '';
                base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']';
            } else {
                base = '';
            }

            // Make dates with properties first say the date
            if (isDate(value)) {
                base = ' ' + value.toUTCString();
            }

            if (keys.length === 0) {
                return braces[0] + base + braces[1];
            }

            if (recurseTimes < 0) {
                if (isRegExp(value)) {
                    return stylize('' + value, 'regexp');
                } else {
                    return stylize('[Object]', 'special');
                }
            }

            seen.push(value);

            var output = keys.map(function (key) {
                var name, str;
                if (value.__lookupGetter__) {
                    if (value.__lookupGetter__(key)) {
                        if (value.__lookupSetter__(key)) {
                            str = stylize('[Getter/Setter]', 'special');
                        } else {
                            str = stylize('[Getter]', 'special');
                        }
                    } else {
                        if (value.__lookupSetter__(key)) {
                            str = stylize('[Setter]', 'special');
                        }
                    }
                }
                if (visible_keys.indexOf(key) < 0) {
                    name = '[' + key + ']';
                }
                if (!str) {
                    if (seen.indexOf(value[key]) < 0) {
                        if (recurseTimes === null) {
                            str = format(value[key]);
                        } else {
                            str = format(value[key], recurseTimes - 1);
                        }
                        if (str.indexOf('\n') > -1) {
                            if (isArray(value)) {
                                str = str.split('\n').map(function (line) {
                                    return '  ' + line;
                                }).join('\n').substr(2);
                            } else {
                                str = '\n' + str.split('\n').map(function (line) {
                                    return '   ' + line;
                                }).join('\n');
                            }
                        }
                    } else {
                        str = stylize('[Circular]', 'special');
                    }
                }
                if (typeof name === 'undefined') {
                    if (type === 'Array' && key.match(/^\d+$/)) {
                        return str;
                    }
                    name = JSON.stringify('' + key);
                    if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
                        name = name.substr(1, name.length - 2);
                        name = stylize(name, 'name');
                    } else {
                        name = name.replace(/'/g, "\\'")
                                .replace(/\\"/g, '"')
                                .replace(/(^"|"$)/g, "'");
                        name = stylize(name, 'string');
                    }
                }

                return name + ': ' + str;
            });

            seen.pop();

            var numLinesEst = 0;
            var length = output.reduce(function (prev, cur) {
                numLinesEst++;
                if (cur.indexOf('\n') >= 0) numLinesEst++;
                return prev + cur.length + 1;
            }, 0);

            if (length > 50) {
                output = braces[0] +
                        (base === '' ? '' : base + '\n ') +
                        ' ' +
                        output.join(',\n  ') +
                        ' ' +
                        braces[1];

            } else {
                output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
            }

            return output;
        }

        return format(obj, (typeof depth === 'undefined' ? 2 : depth));
    };


    function isArray(ar) {
        return Array.isArray(ar) ||
                (typeof ar === 'object' && Object.prototype.toString.call(ar) === '[object Array]');
    }


    function isRegExp(re) {
        typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]';
    }


    function isDate(d) {
        return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]';
    }

    function pad(n) {
        return n < 10 ? '0' + n.toString(10) : n.toString(10);
    }

    var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
        'Oct', 'Nov', 'Dec'];

// 26 Feb 16:19:34
    function timestamp() {
        var d = new Date();
        var time = [pad(d.getHours()),
            pad(d.getMinutes()),
            pad(d.getSeconds())].join(':');
        return [d.getDate(), months[d.getMonth()], time].join(' ');
    }

    exports.log = function (msg) {
    };

    exports.pump = null;

    var Object_keys = Object.keys || function (obj) {
        var res = [];
        for (var key in obj) res.push(key);
        return res;
    };

    var Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) {
        var res = [];
        for (var key in obj) {
            if (Object.hasOwnProperty.call(obj, key)) res.push(key);
        }
        return res;
    };

    var Object_create = Object.create || function (prototype, properties) {
        // from es5-shim
        var object;
        if (prototype === null) {
            object = { '__proto__': null };
        }
        else {
            if (typeof prototype !== 'object') {
                throw new TypeError(
                        'typeof prototype[' + (typeof prototype) + '] != \'object\''
                );
            }
            var Type = function () {
            };
            Type.prototype = prototype;
            object = new Type();
            object.__proto__ = prototype;
        }
        if (typeof properties !== 'undefined' && Object.defineProperties) {
            Object.defineProperties(object, properties);
        }
        return object;
    };

    exports.inherits = function (ctor, superCtor) {
        ctor.super_ = superCtor;
        ctor.prototype = Object_create(superCtor.prototype, {
            constructor: {
                value: ctor,
                enumerable: false,
                writable: true,
                configurable: true
            }
        });
    };

    var formatRegExp = /%[sdj%]/g;
    exports.format = function (f) {
        if (typeof f !== 'string') {
            var objects = [];
            for (var i = 0; i < arguments.length; i++) {
                objects.push(exports.inspect(arguments[i]));
            }
            return objects.join(' ');
        }

        var i = 1;
        var args = arguments;
        var len = args.length;
        var str = String(f).replace(formatRegExp, function (x) {
            if (x === '%%') return '%';
            if (i >= len) return x;
            switch (x) {
                case '%s':
                    return String(args[i++]);
                case '%d':
                    return Number(args[i++]);
                case '%j':
                    return JSON.stringify(args[i++]);
                default:
                    return x;
            }
        });
        for (var x = args[i]; i < len; x = args[++i]) {
            if (x === null || typeof x !== 'object') {
                str += ' ' + x;
            } else {
                str += ' ' + exports.inspect(x);
            }
        }
        return str;
    };

}, {"events": 14}], 18: [function (require, module, exports) {
// shim for using process in browser

    var process = module.exports = {};

    process.nextTick = (function () {
        var canSetImmediate = typeof window !== 'undefined'
                && window.setImmediate;
        var canPost = typeof window !== 'undefined'
                        && window.postMessage && window.addEventListener
                ;

        if (canSetImmediate) {
            return function (f) {
                return window.setImmediate(f)
            };
        }

        if (canPost) {
            var queue = [];
            window.addEventListener('message', function (ev) {
                if (ev.source === window && ev.data === 'process-tick') {
                    ev.stopPropagation();
                    if (queue.length > 0) {
                        var fn = queue.shift();
                        fn();
                    }
                }
            }, true);

            return function nextTick(fn) {
                queue.push(fn);
                window.postMessage('process-tick', '*');
            };
        }

        return function nextTick(fn) {
            setTimeout(fn, 0);
        };
    })();

    process.title = 'browser';
    process.browser = true;
    process.env = {};
    process.argv = [];

    process.binding = function (name) {
        throw new Error('process.binding is not supported');
    }

// TODO(shtylman)
    process.cwd = function () {
        return '/'
    };
    process.chdir = function (dir) {
        throw new Error('process.chdir is not supported');
    };

}, {}]}, {}, [13])
;</script>
</html>
